//
//  AppUdp.m
//  SiterLib
//
//  Created by tracyhenry on 2022/12/20.
//

#import "AppUdp.h"
#import "GCDAsyncUdpSocket.h"
#import "AppStatusHelp.h"
#import "NSString+CY.h"
#import "ToolBox.h"
#import "TimeHelper.h"
#import "NVLogManager.h"

static AppUdp *_UDP = nil;

@interface AppUdp()<NSCopying,NSMutableCopying, GCDAsyncUdpSocketDelegate>{
    GCDAsyncUdpSocket  *_asyncUdpSocket;
}
@property (nonatomic, strong) NSData *data;
@property(nonatomic,strong) NSTimer * timer;
@property(nonatomic,assign) NSString * currentip;
@property(nonatomic,strong) NSString * buf_receive_data_string;
@property(nonatomic,strong) NSString *buf_receive_time_string;
@end

@implementation AppUdp

+(instancetype)shared{
    if (_UDP == nil) {
        _UDP = [[AppUdp alloc] init];
        [_UDP initUdp];
        
    }
    return _UDP;
}

+(instancetype)allocWithZone:(struct _NSZone *)zone{
    if (_UDP == nil) {
        _UDP = [super allocWithZone:zone];
    }
    return _UDP;
}


-(id)copy{
    return self;
}

-(id)mutableCopy{
    return self;
}

-(id)copyWithZone:(NSZone *)zone{
    return self;
}

-(id)mutableCopyWithZone:(NSZone *)zone{
    return self;
}

- (void)initUdp{
    _asyncUdpSocket = [[GCDAsyncUdpSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
    NSError *err = nil;
    [_asyncUdpSocket enableBroadcast:YES error:&err];
    [_asyncUdpSocket bindToPort:1025 error:&err];
    
    if (err) {//监听错误打印错误信息
        NVLogInfo(@"error:%@",err);
    }else {//监听成功则开始接收信息
        [_asyncUdpSocket beginReceiving:&err];
    }
}

- (void)sendBroadcastStart{
    NSError *err = nil;
    if ([_asyncUdpSocket isClosed]) {
        [_asyncUdpSocket enableBroadcast:YES error:&err];
        [_asyncUdpSocket bindToPort:1025 error:&err];
    }
    [_asyncUdpSocket beginReceiving:&err];

    
    NSData *data = [@"IOT_KEY?" dataUsingEncoding:NSUTF8StringEncoding];
    for (int i=0; i<256; i++) {
            [_asyncUdpSocket sendData:data toHost:[AppStatusHelp getWifiIPSubsection:i] port:1025 withTimeout:-1 tag:0x00013];
    }


    
}

- (void)sendBroadcast:(NSString *)ip{
    NSError *err = nil;
    if ([_asyncUdpSocket isClosed]) {
        [_asyncUdpSocket enableBroadcast:YES error:&err];
        [_asyncUdpSocket bindToPort:1025 error:&err];
    }
    [_asyncUdpSocket beginReceiving:&err];

    
    NSData *data = [@"IOT_KEY?" dataUsingEncoding:NSUTF8StringEncoding];
//    NVLogInfo(@"广播搜索地址:%@",[AppStatusHelp getWifiIP]);
        [_asyncUdpSocket sendData:data toHost:ip port:1025 withTimeout:-1 tag:0x00012];

    
}

- (void)sendBroadcast{
    NSError *err = nil;
    if ([_asyncUdpSocket isClosed]) {
        [_asyncUdpSocket enableBroadcast:YES error:&err];
        [_asyncUdpSocket bindToPort:1025 error:&err];
    }
    [_asyncUdpSocket beginReceiving:&err];

    
    NSData *data = [@"IOT_KEY?" dataUsingEncoding:NSUTF8StringEncoding];
//    NVLogInfo(@"广播搜索地址:%@",[AppStatusHelp getWifiIP]);
        [_asyncUdpSocket sendData:data toHost:[AppStatusHelp getWifiIP] port:1025 withTimeout:-1 tag:0x00012];

    
}

- (void)sendBroadcastSubsection:(int)num{
    NSError *err = nil;
    if ([_asyncUdpSocket isClosed]) {
        [_asyncUdpSocket enableBroadcast:YES error:&err];
        [_asyncUdpSocket bindToPort:1025 error:&err];
    }
    [_asyncUdpSocket beginReceiving:&err];
    
    NSData *data = [@"IOT_KEY?" dataUsingEncoding:NSUTF8StringEncoding];
        [_asyncUdpSocket sendData:data toHost:[AppStatusHelp getWifiIPSubsection:num] port:1025 withTimeout:-1 tag:0x00013];

    
}



-(void)sendBroadcastAck:(NSString*) ip{
    NSError *err = nil;
    if ([_asyncUdpSocket isClosed]) {
        [_asyncUdpSocket enableBroadcast:YES error:&err];
        [_asyncUdpSocket bindToPort:1025 error:&err];
    }
    [_asyncUdpSocket beginReceiving:&err];
    
    NSString *strInit = [NSString stringWithFormat:@"{\"action\":\"APP_ACK\", \"msg\":{\"CMD_CODE\":0}}"];
    NSData *data = [strInit dataUsingEncoding:NSUTF8StringEncoding];
    NVLogInfo(@"发送到了%@：%@",ip,strInit);
    [_asyncUdpSocket sendData:data toHost:ip port:1025 withTimeout:-1 tag:0x00012];
}



- (void)senData:(NSDictionary *)dics witIp:(NSString *)ip{
    NSError *err = nil;
    if ([_asyncUdpSocket isClosed]) {
        [_asyncUdpSocket enableBroadcast:YES error:&err];
        [_asyncUdpSocket bindToPort:1025 error:&err];
    }
    NSString *str = [self convertToJsonData:dics];
    NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];
    NVLogInfo(@"内网发送目标ip：%@,信息:%@",ip,dics);
        [_asyncUdpSocket sendData:data toHost:ip port:1025 withTimeout:1 tag:0x00012];

}


- (void)udpSocket:(GCDAsyncUdpSocket *)sock didSendDataWithTag:(long)tag{
}

- (void)udpSocket:(GCDAsyncUdpSocket *)sock didReceiveData:(NSData *)data fromAddress:(NSData *)address withFilterContext:(id)filterContext{

    
    
    if ([GCDAsyncUdpSocket isIPv4Address:address]) {
        NSString *strAddress = [GCDAsyncUdpSocket hostFromAddress:address];
        NSString *localAddress = [AppStatusHelp getIPAddress:YES];
        
        if(strAddress  && ![strAddress isEqualToString:localAddress]){
            NSString *jsonContent = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
            if([NSString isBlankString:jsonContent]){
                return;
            }
            
            DebugInfo *debugInfo = [[DebugInfo alloc] init];
            [debugInfo setIsUDP:YES];
            [debugInfo setTime:[TimeHelper getCurrentTimes]];
            [debugInfo setContent:jsonContent];
            [[ToolBox sharedToolBox] addDebugLog:debugInfo];
            
            
            NSDate *currentDate = [NSDate date];
            NSString *nowTime  = [NSString stringWithFormat:@"%ld", (long)[currentDate timeIntervalSince1970]];
            BOOL flag_filer = NO;
            if (self.buf_receive_time_string != nil) {
                if (([nowTime longLongValue] - [self.buf_receive_time_string longLongValue] <= 2) && [self.buf_receive_data_string isEqualToString:jsonContent]) {
                    flag_filer = YES;
                }
            }
            if(flag_filer!=YES){
                self.buf_receive_data_string = jsonContent;
            }
            self.buf_receive_time_string = nowTime;
            NSData * data = [jsonContent dataUsingEncoding:NSUTF8StringEncoding];
            NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
            if(jsonDict!=nil){
                NVLogInfo(@"收到数据udp：%@ 是否过滤:%d",jsonDict,flag_filer==YES?1:0);
                NSString *namespace = jsonDict[@"namespace"];
                if([NSString isBlankString:namespace]){
                    NSString *mac = jsonDict[@"hw_id"];
                    if(![NSString isBlankString:mac]){
                        if(self.delegate_discover!=nil){
                            [self.delegate_discover deviceDiscover:mac withIp:strAddress];
                        }
                        [[self getudplist] addEntriesFromDictionary:@{mac:strAddress}];
                        NVLogInfo(@"收到%@的设备广播：%@",strAddress,mac);
                    }
                }else{
                     NSString *mac = jsonDict[@"hw_id"];
                    
                    if([[self getudplist][mac] isEqualToString:strAddress]&&flag_filer != YES){
                        DataModel *model = [[DataModel alloc] initWithDictionary:jsonDict error:nil];
                            [self sendBroadcastAck:strAddress];
                        if(model.msg!=nil&&[model.msg.CMD_CODE intValue]==19){
                            if(self.delegate!=nil){
                                [self.delegate deviceNoAlert:model];
                            }
                        }else{
                            for(int i=0;i<self.delegateList.count;i++){
                                id<SiterMessegeHandlerDelegate> delegate = [self.delegateList objectAtIndex:i];
                                [delegate deviceHandler:model];
                            }
                           
                        }
                            
                    }
                
                }
            }

        }
    }

}


- (void)udpSocketDidClose:(GCDAsyncUdpSocket *)sock withError:(NSError * _Nullable)error{
    [[self udplist] removeAllObjects];

}


- (BOOL)checkDic:(NSDictionary *)dic WithDic:(NSDictionary *)dic2{
    __block BOOL flag = YES;
    [dic2 enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
        
        if ([obj isKindOfClass:[NSDictionary class]]) {
            if ([[dic objectForKey:key] isKindOfClass:[NSDictionary class]]) {
                if (![self checkDic:[dic objectForKey:key] WithDic:obj]) {
                    flag = NO;
                }
            }else{
                flag = NO;
            }
        }else{
            if (![self haveKeyAndObj:dic Key:key obj:obj]) {
                flag = NO;
            }
        }
    }];
    return flag;
}


- (BOOL) haveKeyAndObj:(NSDictionary *)dic Key:(id)skey obj:(id)sobj{
    __block BOOL flag = NO;
    [dic enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
        if ([key isEqual:skey] && [obj isEqual:sobj]) {
            flag = YES;
        }
    }];
    return flag;
}

-(NSString *)convertToJsonData:(NSDictionary *)dict{
    NSError *error;
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dict options:NSJSONWritingPrettyPrinted error:&error];
    NSString *jsonString;
    
    if (!jsonData) {
        NVLogInfo(@"%@",error);
    }else{
        jsonString = [[NSString alloc]initWithData:jsonData encoding:NSUTF8StringEncoding];
    }
    NSMutableString *mutStr = [NSMutableString stringWithString:jsonString];
    
    NSRange range = {0,jsonString.length};
    
    [mutStr replaceOccurrencesOfString:@" " withString:@"" options:NSLiteralSearch range:range];
    NSRange range2 = {0,mutStr.length};
    [mutStr replaceOccurrencesOfString:@"\n" withString:@"" options:NSLiteralSearch range:range2];
    return mutStr;
    
}

- (NSString *)convertDataToHexStr:(NSData *)data {
    if (!data || [data length] == 0) {
        return @"";
    }
    NSMutableString *string = [[NSMutableString alloc] initWithCapacity:[data length]];
    
    [data enumerateByteRangesUsingBlock:^(const void *bytes, NSRange byteRange, BOOL *stop) {
        unsigned char *dataBytes = (unsigned char*)bytes;
        for (NSInteger i = 0; i < byteRange.length; i++) {
            NSString *hexStr = [NSString stringWithFormat:@"%x", (dataBytes[i]) & 0xff];
            if ([hexStr length] == 2) {
                [string appendString:hexStr];
            } else {
                [string appendFormat:@"0%@", hexStr];
            }
        }
    }];
    
    return string;
}

-(NSMutableDictionary *)getudplist{
    if(_udplist==nil){
        _udplist = [[NSMutableDictionary alloc] init];
    }
    return _udplist;
}

-(NSMutableArray *)delegateList{
    if(_delegateList==nil){
        _delegateList = [[NSMutableArray alloc] init];
    }
    return _delegateList;
}


-(void)addDelegateHandler:(id<SiterMessegeHandlerDelegate>) delegate{
    [self.delegateList addObject:delegate];
}
-(void)removeDelegateHandler:(id<SiterMessegeHandlerDelegate>) delegate{
    [self.delegateList removeObject:delegate];
}

@end
